/*
 * name: mabel xu
 * date: november 2, 2007
 * filename: StackQueueTest.java
 * description: a StackQueue Reverse Polish Notational calculator that works from and prints to an output file
 */

import java.util.*;		// work with stacks and queues
import java.io.*;		// input and output to files
import java.lang.*;		// work with characters

public class StackQueueTest
{
	private static Stack<Integer> calculator;
	private static Queue<String> output;

	public static void main(String args[])
	{
		try		// try to open the input file
		{
			calculator = new Stack<Integer>();
			output = new LinkedList<String>();

			Scanner infile = new Scanner(new File("StackQueueRPNinput.txt"));
			char item = ' ';

			// keep getting from input file until there's a q, process each input as its gotten
			while (item != 'Q' && item != 'q')
			{
				item = infile.next().charAt(0);
				output.add(new Character(item).toString());
				output.add(new String("\t"));
				if (isNumber(item))		// if input is number, add to stack
					calculator.add(new Integer(Character.getNumericValue(item)));
				else		// if an operator, perform the operation
					operate(item);
			}	// should've finished getting from input file by now

			try		// try to open an output file
			{
				FileOut outfile = new FileOut("StackQueueRPNoutput.txt");
				String problem = "";
				String temp= "";

				// keep outputting all the output collected in the queue until all gone
				while (!output.isEmpty())
				{
					// this section is a hack to get round the fact that there's no outfile.print(), only an outfile.println()
					temp = output.remove();
					if(temp.equals("\n"))		// if there's a new line, output a line (one problem)
					{
						outfile.println(problem);
						problem = "";
					}
					else		// keep collecting stuff until ready to print a line
						problem += temp;
				}			// should end with queue empty, all items processed

			}
			catch (Exception e)		// in case output file cannot be opened
			{
				System.out.println("Sorry, invalid output file");
			}		// by now the entire program should be done running (in the case inputfile is ok)
		}
		catch (FileNotFoundException e)		// in case input file not found
		{
			System.out.println("Sorry, invalid input file");
		}		// end of the entire check for input file try-catch
	}		// end of main method

	// given a char, will check to see if it is a number (0 - 9) and return true or false
	// does not affect queue or stack content
	private static boolean isNumber(char c)
	{
		switch (c)		// given that parameter is:
		{
			// fall through on purpose ...
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':	return true;	// 0 - 9, then it is a number (so return true)
			default:	return false;	// otherwise, it's not a number (so return false)
		}		// should never reach this, since return true or return false will short circuit
	}		// end of isNumber method

	// given a char, decides which operation to do
	// does not affect any data
	private static void operate(char operator)
	{
		switch (operator)		// depending on operator, call correct method
		{
			case '+':	add();		break;
			case '-':	subtract();	break;
			case '*':	multiply();	break;
			case '/':	divide();	break;
			case '=':	equals();	break;
		}		// end of "deciding which method to call" section
	}		// end of operate method

	// pops 2 Integers off of the stack, adds then, pushes on the result as an Integer
	// requires 2 Integers to already be on the stack, result
	private static void add()
	{
		int b = calculator.pop().intValue();
		int a = calculator.pop().intValue();
		int result = a + b;

		calculator.push(new Integer(result));
	}

	private static void subtract()
	{
		int b = calculator.pop().intValue();
		int a = calculator.pop().intValue();
		int result = a - b;

		calculator.push(new Integer(result));
	}

	private static void multiply()
	{
		int b = calculator.pop().intValue();
		int a = calculator.pop().intValue();
		int result = a * b;

		calculator.push(new Integer(result));
	}

	private static void divide()
	{
		int b = calculator.pop().intValue();
		int a = calculator.pop().intValue();
		int result = a / b;

		calculator.push(new Integer(result));
	}

	private static void equals()
	{
		Integer result = calculator.peek();
		output.add(result.toString());
		output.add(new String("\n"));
	}
}